package br.com.salaodebeleza.view;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.inject.Inject;

import br.com.salaodebeleza.business.TbCalcularServicosBC;
import br.com.salaodebeleza.business.TbRelatorioDiarioBC;
import br.com.salaodebeleza.domain.TbCalcularServicos;
import br.com.salaodebeleza.domain.TbFuncionario;
import br.com.salaodebeleza.domain.TbRelatorioDiario;
import br.com.salaodebeleza.domain.TbServicos;
import br.com.salaodebeleza.util.CamposRelatorioDiario;
import br.com.salaodebeleza.util.UtilidadesRelatorioDiario;
import br.gov.frameworkdemoiselle.annotation.NextView;
import br.gov.frameworkdemoiselle.stereotype.ViewController;
import br.gov.frameworkdemoiselle.template.AbstractEditPageBean;
import br.gov.frameworkdemoiselle.transaction.Transactional;


@ViewController
@NextView("./tbRelatorioDiario_list.jsf")
public class TbRelatorioDiarioEditMB extends
		AbstractEditPageBean<TbRelatorioDiario, Long> {

	private static final long serialVersionUID = 1L;

	private Double vlTotalSalao = 0.0;
	private Double vlTotalServicos = 0.0;
	private List<CamposRelatorioDiario> columns;
	private List<TbCalcularServicos> dataModel;

	@Inject
    private FacesContext facesContext;
	
	@Inject
	private TbRelatorioDiarioBC tbRelatorioDiarioBC;
	
	@Inject
	private TbCalcularServicosBC tbCalcularServicosBC;
	
	private TbRelatorioDiario tbRelatorioDiario = new TbRelatorioDiario();

	@Override
	@Transactional
	public String delete() {
		this.tbRelatorioDiarioBC.delete(getId());
		return getPreviousView();
	}

	@Override
	@Transactional
	public String insert() {
		this.tbRelatorioDiarioBC.insert(getBean());
		return getPreviousView();
	}

	@Override
	@Transactional
	public String update() {
		this.tbRelatorioDiarioBC.update(getBean());
		return getPreviousView();
	}

	@Override
	protected void handleLoad() {
		//setBean(this.tbRelatorioDiarioBC.load(getId()));
	}

	public List<CamposRelatorioDiario> getColumns() {
		return columns;
	}

	public void setColumns(List<CamposRelatorioDiario> columns) {
		this.columns = columns;
	}
	
	public String emitirRelatorio() {

		try {
			this.vlTotalServicos = 0.0;
			this.vlTotalSalao = 0.0;
			columns = new ArrayList<CamposRelatorioDiario>();
			
			dataModel = tbCalcularServicosBC.findByMenuJPQL(tbRelatorioDiario.getDtInicio(),
					tbRelatorioDiario.getDtFim());

			if (dataModel.size() == 0) {
			
				FacesMessage message = new FacesMessage(
						FacesMessage.SEVERITY_INFO, "Nenhum dado encontrado!",
						"Nenhum dado encontrado!");
				facesContext.addMessage(null, message);
			
			} else {
				
				Long idFuncionario;
				List<TbServicos> listServicos = null;
				HashMap<Long, TbFuncionario> mapFuncionarios = new HashMap<Long, TbFuncionario>();
				HashMap<Long, List<TbServicos>> mapFuncServico = new HashMap<Long, List<TbServicos>>();
				
				for (TbCalcularServicos calcularServicos : dataModel) {
					
					idFuncionario = calcularServicos.getTbFuncionario().getId();
					
					// Popula mapa de funcionarios
					if (!mapFuncionarios.containsKey(idFuncionario)) {
						mapFuncionarios.put(idFuncionario, calcularServicos.getTbFuncionario());
					} 	
					
					// Popula mapa de funcionarios com sua lista de serviços
					if (!mapFuncServico.containsKey(idFuncionario)) {
						listServicos = new ArrayList<TbServicos>();
						listServicos.add(calcularServicos.getTbServico());
						mapFuncServico.put(idFuncionario, listServicos);
					} else {
						listServicos = mapFuncServico.get(idFuncionario);
						listServicos.add(calcularServicos.getTbServico());
					}	
					
				} // for (TbCalcularServicos calcularServicos : dataModel) 
				
				Integer qtdServicos;
				CamposRelatorioDiario campo;
				HashMap<Long, TbServicos> mapServicos;
				HashMap<Long, Integer> mapQtdServicos;
				for (Map.Entry<Long, List<TbServicos>> entryFunc : mapFuncServico.entrySet()) {  
					
					
					mapServicos = new HashMap<Long, TbServicos>();
					mapQtdServicos = new HashMap<Long, Integer>();
					List<TbServicos> servicos = entryFunc.getValue();
					
					for (TbServicos servico : servicos) {
						
						// Popula mapa de quantidade de cada servico por funcionario
						qtdServicos = 0;
						if (!mapQtdServicos.containsKey(servico.getId())) {
							qtdServicos++;						
						} else {
							qtdServicos= mapQtdServicos.get(servico.getId()) + 1 ;
						}
						
						mapQtdServicos.put(servico.getId(), qtdServicos);
												
						// Popula mapa de servicos por funcionario
						if(!mapServicos.containsKey(servico.getId())){
							mapServicos.put(servico.getId(), servico);
						}

					} // for (TbServicos servico : servicos)

					Double vlUnitarioServico;
					Integer percentual;
					for (Map.Entry<Long, Integer> entryServ : mapQtdServicos.entrySet()) {
						campo = new CamposRelatorioDiario();
						idFuncionario = entryFunc.getKey();
						percentual = mapServicos.get(entryServ.getKey()).getPc_salao();
						vlUnitarioServico = mapServicos.get(entryServ.getKey()).getVlServico();
						qtdServicos = entryServ.getValue();
						
						campo.setFuncionario(mapFuncionarios.get(idFuncionario).getNmFuncionario());
						campo.setIdFuncionario(idFuncionario);
						campo.setQtdServicos(qtdServicos);
						campo.setServico(mapServicos.get(entryServ.getKey()).getNmServico());
						campo.setVlTotalServico(UtilidadesRelatorioDiario.calcularTotalServicos(qtdServicos, vlUnitarioServico));
						campo.setVlUnitServico(vlUnitarioServico);
						campo.setPcSalao(UtilidadesRelatorioDiario.calcularPercentualSalao(campo.getVlTotalServico(), percentual));
						campo.setPcFuncionario(UtilidadesRelatorioDiario.calcularPercentualFuncionario(campo.getVlTotalServico(), campo.getPcSalao()));
						
						columns.add(campo);
						
					}
					
				} // for (Map.Entry<Long, List<TbServicos>> entry : mapFuncionarios.entrySet())
				
				calcularTotais(columns);
				
			} // else

			return "";

		} catch (Exception e) {
			FacesMessage message = new FacesMessage(
					FacesMessage.SEVERITY_FATAL, e.getLocalizedMessage(), "");
			facesContext.addMessage(null, message);
			return "";
		}
	}
	
	private void calcularTotais(List<CamposRelatorioDiario> columns){
		
		for(CamposRelatorioDiario campo : columns){
			this.vlTotalServicos+= campo.getVlTotalServico();
			this.vlTotalSalao+= campo.getPcSalao();
		}
		
	}

	
	public Double getVlTotalSalao() {
		return vlTotalSalao;
	}

	public void setVlTotalSalao(Double vlTotalSalao) {
		this.vlTotalSalao = vlTotalSalao;
	}

	public Double getVlTotalServicos() {
		return vlTotalServicos;
	}

	public void setVlTotalServicos(Double vlTotalServicos) {
		this.vlTotalServicos = vlTotalServicos;
	}

	public TbRelatorioDiario getTbRelatorioDiario() {
		return tbRelatorioDiario;
	}

	public void setTbRelatorioDiario(TbRelatorioDiario tbRelatorioDiario) {
		this.tbRelatorioDiario = tbRelatorioDiario;
	}	

}